package com.wondream.myframework.app.common.util.bbgJwt;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Component
public class JwtUtils {
	
	private static String secret = "f4e2e52034348f86b67uek581c0f9ao0";
	private static long expire = 1*24*60*60;

    /**
     * 生成jwt token
     */
    public static String generateToken(Map<String, Object> userInfo) {
        HashMap<String, Object> map = new HashMap<>();
        map.put("openId", userInfo.get("openId"));
        map.put("sessionKey", userInfo.get("sessionKey"));
        String subject = objToStrTrim(userInfo.get("userId"));
        return baseToken(map,subject,expire);
    }

	/**
	 * 生成jwt token 临时
	 */
	public static String generateToken_h5(Map<String, Object> userInfo) {
		HashMap<String, Object> map = new HashMap<>();
		map.put("userId", userInfo.get("userId"));
		String subject = objToStrTrim(userInfo.get("userId"));
		return baseToken(map,subject,60*60*1);
	}

	/**
	 * 解析临时token
	 * @return  true：过期
	 */
	public static Map<String, String> parserToken_h5(String token) throws AuthFailException{
		// 解密token
		Claims claims = JwtUtils.getClaimByToken(token);
		if(claims == null) {
			return null;
		}
		Map<String, String> map = new HashMap<String, String>();
		map.put("userId", (String)claims.get("userId"));
		return map;
	}

	/**
	 * 生成jwt token
	 */
	public static String baseToken(HashMap<String, Object> map,String subject,long expire_ms) {
		Date nowDate = new Date();
		return Jwts.builder()
				.setHeaderParam("typ", "JWT")
				.addClaims(map)
				.setSubject(subject)
				.setIssuedAt(nowDate)
				.setExpiration(new Date(nowDate.getTime() + expire_ms * 1000))
				.signWith(io.jsonwebtoken.SignatureAlgorithm.HS512, secret)
				.compact();
	}


    public static Claims getClaimByToken(String token) {
        try {
            return Jwts.parser()
                    .setSigningKey(secret)
                    .parseClaimsJws(token)
                    .getBody();
        }catch (Exception e){
            return null;
        }
    }
    
    /**
     * token是否过期
     * @return  true：过期
     */
    public static boolean isTokenExpired(Claims claims) throws HyException {
    	Date expiration = claims.getExpiration();
    	if (HyDateUtil.getDatesBetweenTwoDate(HyDateUtil.SDF_NO_SPLIT_DATE_SHORT.format(expiration),  HyDateUtil.getCurrentDate()) != 0) {
			return false;
		}
        return expiration.before(new Date());
    }
    
    /**
     * 校验token是否合法
     * @return  true：过期
     */
    public static void validateToken(String requestUserId, Claims claims) throws AuthFailException {
    	
    	if(StringUtils.isBlank(requestUserId) || claims == null || StringUtils.isBlank(claims.getSubject())) {
    		throw new AuthFailException("用户未登录");
    	}
    	
		String userId = claims.getSubject();
		// 用户Id一致校验
		if(!userId.equals(requestUserId)) {
    		throw new AuthFailException("用户未登录");
		}
		
		// token过期
		try {
			if(isTokenExpired(claims)) {
				throw new AuthFailException("登录状态过期");
			}
		} catch (HyException e) {
			throw new AuthFailException("登录状态过期");
		}
	}

    /**
     * 解析sessionInfo
     * @return  true：过期
     */
    public static Map<String, String> parseMappSessionInfo(String token) {
    	// 解密token
    	Claims claims = JwtUtils.getClaimByToken(token);
		if(claims == null) {
			return null;
		}

		Map<String, String> sessionInfo = new HashMap<String, String>();
		sessionInfo.put("openId", (String)claims.get("openId"));
		sessionInfo.put("sessionKey", (String)claims.get("sessionKey"));
		return sessionInfo;
    }

    /**
     * 解析userInfo
     * @return  true：过期
     */
    public static Map<String, Object> parseUserInfo(String requestUserId, String token) throws AuthFailException {
    	// 解密token
    	Claims claims = JwtUtils.getClaimByToken(token);
		if(claims == null) {
			return null;
		}
		
		// 校验用户Token
		validateToken(requestUserId, claims);
		
		Map<String, Object> userInfo = new HashMap<>();
		userInfo.put("userId", claims.getSubject());
		userInfo.put("openId", claims.get("openId"));
		userInfo.put("sessionKey", claims.get("sessionKey"));
		return userInfo;
    }

	/**
	 * object对象转换为String
	 *
	 * @param obj
	 * @return
	 */
	public static String objToStrTrim(Object obj) {
		return obj == null ? "" : obj.toString().trim();
	}
}